﻿using AudioLabelerTool;
using HimVoiceStudioCore;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HimVoiceStudio
{
    public partial class FrmCutAudio : Form
    {
        public FrmCutAudio()
        {
            InitializeComponent();
        }
        PositionalAudioPlayer player;
        SpliceParam currentSpliceParam;
        public static SpliceParam ShowCutWindow(Form owner,string audioPath,SpliceParam spliceParam)
        {
            FrmCutAudio frmCutAudio = new FrmCutAudio();
            frmCutAudio.player = new PositionalAudioPlayer(audioPath);
            frmCutAudio.currentSpliceParam = spliceParam == null ? null : new SpliceParam() { start = spliceParam.start,end = spliceParam.end};
            frmCutAudio.StartPosition = FormStartPosition.CenterParent;
            var result = frmCutAudio.ShowDialog(owner);
            if(result == DialogResult.OK)
            {
                return frmCutAudio.currentSpliceParam;
            }
            return null;
        }

        private void loadAudioSpectrum(PositionalAudioPlayer player, WaveformRenderControl wav)
        {
            wav.setWaveform(null);
            if (player != null)
            {
                float seconds = player.TotalSecond;
                float totalPixels = wav.ClientSize.Width - 3;

                float newPixelPerSeconds = totalPixels / seconds;
                wav.setPixelPerSecond(newPixelPerSeconds);
                using (AudioFileReader afr = new AudioFileReader(player.AudioPath))
                {
                    wav.setWaveform(wav.scanForWaveFile(afr));
                }

            }

        }

        private void FrmCutAudio_Load(object sender, EventArgs e)
        {
            button1.Enabled = this.currentSpliceParam != null;
            
            loadAudioSpectrum(player, waveformRenderControl1);
            if (this.currentSpliceParam != null)
            {
                waveformRenderControl1.SetSelection(currentSpliceParam.start, currentSpliceParam.end);
                waveformRenderControl1_SelectionChanged(null, null);
            }
        }

        private class PositionalAudioPlayer : IDisposable
        {
            public string AudioPath;
            private AudioFileReader audioFileReader;
            private WasapiOut waveOut;
            public PositionalAudioPlayer(string audioPath)
            {
                this.AudioPath = audioPath;
                audioFileReader = new AudioFileReader(audioPath);
                waveOut = new WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Shared, 32);

                waveOut.Init(audioFileReader);

            }

            public bool IsPlaying
            {
                get
                {
                    return waveOut.PlaybackState == PlaybackState.Playing;
                }
                set
                {
                    if (value)
                    {
                        waveOut.Play();
                    }
                    else
                    {
                        waveOut.Pause();

                    }
                }
            }

            public float TotalSecond
            {
                get
                {
                    return (float)audioFileReader.TotalTime.TotalSeconds;
                }
            }

            public float Position
            {
                get
                {
                    return (float)audioFileReader.CurrentTime.TotalSeconds;

                }
                set
                {
                    audioFileReader.CurrentTime = TimeSpan.FromSeconds(value);
                }
            }


            public void Dispose()
            {
                try
                {
                    waveOut?.Dispose();
                    audioFileReader?.Dispose();
                }
                catch { }
            }
        }

        private void waveformRenderControl1_PreviewClick(object sender, float e)
        {
            stopSecond = -1;
            player.Position = e;
            player.IsPlaying = true;
            animTimer.Start();
        }

        private float stopSecond = -1;

        private void animTimer_Tick(object sender, EventArgs e)
        {
            if (player.IsPlaying)
            {
                if(stopSecond > 0)
                {
                    if(player.Position > stopSecond)
                    {
                        player.IsPlaying = false;
                        animTimer.Stop();
                    }
                }
                waveformRenderControl1.SetPlayingPos(player.Position);
            }
            else
            {

                waveformRenderControl1.SetPlayingPos(-1);
                animTimer.Stop();
            }
        }

        private void btnInPlay_Click(object sender, EventArgs e)
        {
            if(currentSpliceParam == null)
            {
                player.Position = 0;
                stopSecond = -1;
            }
            else
            {
                player.Position = currentSpliceParam.start;
                stopSecond = currentSpliceParam.end;
            }
            player.IsPlaying = true;
            animTimer.Start();
        }

        private void btnInStop_Click(object sender, EventArgs e)
        {
            player.IsPlaying = false;
        }

        private void waveformRenderControl1_SelectionChanged(object sender, EventArgs e)
        {
            if(waveformRenderControl1.HasSelection)
            {
                if (this.currentSpliceParam == null) {
                    this.currentSpliceParam = new SpliceParam();
                }
                currentSpliceParam.start = waveformRenderControl1.SelectionStart;
                currentSpliceParam.end = waveformRenderControl1.SelectionEnd;
                lblEnd.Text = currentSpliceParam.end.ToString("0.00");
                lblStart.Text = currentSpliceParam.start.ToString("0.00");
            }
            else
            {
                this.currentSpliceParam = null;
                lblEnd.Text = "--";
                lblStart.Text = "--";
            }
            button1.Enabled = this.currentSpliceParam != null;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            DialogResult = DialogResult.OK;
            Close();
        }
    }
}
